function TurboModule(stdlib, foreign, buffer) {
    "use asm";
    //##################################
    //#            RUNTIME             #
    //##################################
    var HEAP8 = new stdlib.Int8Array(buffer);
    var HEAP16 = new stdlib.Int16Array(buffer);
    var HEAP32 = new stdlib.Int32Array(buffer);
    var HEAPU8 = new stdlib.Uint8Array(buffer);
    var HEAPU16 = new stdlib.Uint16Array(buffer);
    var HEAPU32 = new stdlib.Uint32Array(buffer);
    var HEAPF32 = new stdlib.Float32Array(buffer);
    var HEAPF64 = new stdlib.Float64Array(buffer);
    
    var NULL = 0;
    var fround = stdlib.Math.fround;
    var imul = stdlib.Math.imul;
    
    //##################################
    //#            IMPORTS             #
    //##################################
    
    //##################################
    //#       MEMORY INITIALIZER       #
    //##################################
    function initMemory() {
        HEAPU8[8] = 219; HEAPU8[9] = 15; HEAPU8[10] = 73; HEAPU8[11] = 64; 
        HEAPU8[12] = 40; HEAPU8[13] = 0; HEAPU8[14] = 0; HEAPU8[15] = 0; 
        HEAPU8[16] = 40; HEAPU8[17] = 0; HEAPU8[18] = 0; HEAPU8[19] = 0; 
        HEAPU8[20] = 0; HEAPU8[21] = 0; HEAPU8[22] = 0; HEAPU8[23] = 0; 
        HEAPU8[24] = 0; HEAPU8[25] = 0; HEAPU8[26] = 0; HEAPU8[27] = 0; 
        HEAPU8[28] = 0; HEAPU8[29] = 0; HEAPU8[30] = 0; HEAPU8[31] = 0; 
        HEAPU8[32] = 0; HEAPU8[33] = 0; HEAPU8[34] = 0; HEAPU8[35] = 0; 
        HEAPU8[36] = 0; HEAPU8[37] = 0; HEAPU8[38] = 0; HEAPU8[39] = 0; 
    }
    
    //##################################
    //#             CODE               #
    //##################################
    
    function malloc(size) {
        size = size|0;
        var alignment = 8;
        var chunkSize = 0;
        var freeChunk = 0;
        var offset = 0;
        var top = 0;
        var ptr = 0;
        size = (((((((((((size|0) + ((((((alignment|0) - 1)|0)))|0))|0))|0) & (~(alignment - 1) | 0))|0))|0))|0);
        chunkSize = (((size|0) + 8)|0);
        freeChunk = (getFreeChunk((chunkSize|0))|0);
        
        if (((((freeChunk|0) | 0) > 0)|0)) {
            return (freeChunk)|0;
        }
        
        offset = (HEAP32[(16) >> 2]|0) | 0;
        offset = (((((((offset|0) + 7)|0))|0))|0);
        offset = (((((((offset|0) & -8)|0))|0))|0);
        top = (((offset|0) + (chunkSize|0))|0);
        ptr = (((offset|0) + 4)|0);
        setHeadSize((ptr|0), (chunkSize|0));
        setInuse((((ptr|0) + 4)|0));
        setFoot((ptr|0), (chunkSize|0));
        HEAP32[(16) >> 2] = (((top|0) + 4)|0);
        offset = (((((((offset|0) + 8)|0))|0))|0);
        ptr = (((offset|0))|0);
        
        while (((((ptr|0) | 0) < ((top|0) | 0))|0)) {
            HEAP32[(ptr ) >> 2] = 0;
            ptr = (((((((ptr|0) + 4)|0))|0))|0);
        }
        return (offset)|0;
    }
    
    
    function free(ptr) {
        ptr = ptr|0;
        var chunkptr = 0;
        var tmp1 = 0;
        chunkptr = 0;
        clearInuse((ptr|0));
        
        if (((((HEAP32[(28) >> 2]|0) == 0)|0))) {
            HEAP32[(28) >> 2] = (ptr|0) | 0;
        }
        
        tmp1 = (((HEAP32[(20) >> 2]|0) | 0)|0);
        tmp1 = (((((((tmp1|0) + ((getChunkSize((ptr|0))|0) | 0))|0))|0))|0);
        HEAP32[(20) >> 2] = (tmp1|0) | 0;
        chunkptr = (((((((ptr|0) + 4)|0))|0))|0);
        
        if ((((HEAP32[(32) >> 2]|0) > 0)|0)) {
            HEAP32[(chunkptr ) >> 2] = (HEAP32[(32) >> 2]|0);
            HEAP32[((HEAP32[(32) >> 2]|0) ) >> 2] = (ptr|0) | 0;
        }
        
        else {
            HEAP32[(chunkptr ) >> 2] = 0;
        }
        
        HEAP32[(ptr ) >> 2] = 0;
        HEAP32[(32) >> 2] = (ptr|0) | 0;
        HEAP32[(24) >> 2] = (((HEAP32[(24) >> 2]|0) + 1)|0);
    }
    
    
    function getFreeChunk(size) {
        size = size|0;
        var freeChunk = 0;
        var tmp1 = 0;
        var tmp2 = 0;
        var tmp3 = 0;
        var tmp4 = 0;
        freeChunk = 0;
        tmp1 = (((HEAP32[(28) >> 2]|0))|0);
        tmp2 = (((HEAP32[(32) >> 2]|0))|0);
        tmp3 = (((HEAP32[(20) >> 2]|0))|0);
        
        if ((((HEAP32[(24) >> 2]|0) > 0)|0)) {
            freeChunk = (((findChunk((size|0))|0))|0);
            
            if (((((freeChunk|0) | 0) > 0)|0)) {
                if ((((((freeChunk|0) | 0) == (tmp1|0))|0))) {
                    HEAP32[(28) >> 2] = (nextFree((freeChunk|0))|0) | 0;
                }
                
                if ((((((freeChunk|0) | 0) == (tmp2|0))|0))) {
                    HEAP32[(32) >> 2] = 0;
                }
                
                HEAP32[(24) >> 2] = (((HEAP32[(24) >> 2]|0) - 1)|0);
                setInuse((freeChunk|0));
                tmp4 = (((getChunkSize((freeChunk|0))|0))|0);
                tmp3 = (((((((tmp3|0) - (tmp4|0))|0))|0))|0);
                HEAP32[(20) >> 2] = (tmp3|0);
                return (freeChunk)|0;
            }
        }
        return 0;
    }
    
    
    function findChunk(size) {
        size = size|0;
        var chunk = 0;
        var tmp1 = 0;
        chunk = 0;
        chunk = (((HEAP32[(28) >> 2]|0))|0);
        
        while ((((chunk|0) != 0)|0)) {
            tmp1 = (((getChunkSize((chunk|0))|0))|0);
            
            if (((((tmp1|0) == (size|0))|0))) {
                return (chunk)|0;
            }
            
            chunk = (((HEAP32[(chunk ) >> 2]|0))|0);
        }
        return 0;
    }
    
    
    function getHeapPtr() {
        return ((HEAP32[(16) >> 2]|0) | 0)|0;
    }
    
    
    function getFreeMemory() {
        return ((HEAP32[(20) >> 2]|0))|0;
    }
    
    
    function getOriginalHeapPtr() {
        return ((HEAP32[(12) >> 2]|0) | 0)|0;
    }
    
    
    function nextFree(ptr) {
        ptr = ptr|0;
        return ((HEAP32[(ptr ) >> 2]|0) | 0)|0;
    }
    
    
    function setHeadSize(ptr, s) {
        ptr = ptr|0;
        s = s|0;
        HEAP32[(ptr ) >> 2] = (((((((HEAP32[(ptr ) >> 2]|0) & 7)|0))|0) | (s|0))|0);
    }
    
    
    function setFoot(ptr, s) {
        ptr = ptr|0;
        s = s|0;
        var chunkptr = 0;
        var size = 0;
        size = (((HEAP32[(ptr ) >> 2]|0))|0);
        chunkptr = ((((((((ptr|0) | 0) + (size|0))|0))|0))|0);
        HEAP32[(chunkptr ) >> 2] = (s|0);
    }
    
    
    function setInuse(ptr) {
        ptr = ptr|0;
        var chunkptr = 0;
        chunkptr = ((((((((ptr|0) | 0) - 4)|0))|0))|0);
        HEAP32[(chunkptr ) >> 2] = (((HEAP32[(chunkptr ) >> 2]|0) | 1)|0);
    }
    
    
    function clearInuse(ptr) {
        ptr = ptr|0;
        var chunkptr = 0;
        chunkptr = ((((((((ptr|0) | 0) - 4)|0))|0))|0);
        HEAP32[(chunkptr ) >> 2] = (((HEAP32[(chunkptr ) >> 2]|0) & -2)|0);
    }
    
    
    function getChunkSize(ptr) {
        ptr = ptr|0;
        var chunkptr = 0;
        chunkptr = ((((((((ptr|0) | 0) - 4)|0))|0))|0);
        return (((HEAP32[(chunkptr ) >> 2]|0) & -2)|0);
    }
    
    
    function addTwo1(a, b) {
        a = a|0;
        b = b|0;
        return ((a + b)|0);
    }
    
    
    function addTwo2(a, b) {
        a = a|0;
        b = b|0;
        return ((a + b)|0);
    }
    
    
    function addTwo3(a, b) {
        a = fround(a);
        b = fround(b);
        return fround(a + b);
    }
    
    
    function addTwo4(a, b) {
        a = +a;
        b = +b;
        return +(a + b);
    }
    
    
    function fixIndexs(indexs, max_index) {
        indexs = indexs|0;
        max_index = max_index|0;
        var decimal = 0;
        decimal = (((max_index|0) + 1)|0);
        return (1)|0;
    }
    
    
    return {
       initMemory:initMemory,
       malloc:malloc,
       free:free,
       getHeapPtr:getHeapPtr,
       getFreeMemory:getFreeMemory,
       getOriginalHeapPtr:getOriginalHeapPtr,
       addTwo1:addTwo1,
       addTwo2:addTwo2,
       addTwo3:addTwo3,
       addTwo4:addTwo4
    }
}
function TurboASMWrapper(exports, buffer) {

    exports.initMemory();

    return {
        exports: exports,
        RAW_MEMORY: buffer,

        getMemoryUsage: function () {
            const top = Atomics.load(HEAP32, 2);
            // top -= freeMemory;
            return Math.fround(top / (1024 * 1024));
        },
        HEAP8: new Int8Array(buffer),
        HEAP16: new Int16Array(buffer),
        HEAP32: new Int32Array(buffer),
        HEAPU8: new Uint8Array(buffer),
        HEAPU16: new Uint16Array(buffer),
        HEAPU32: new Uint32Array(buffer),
        HEAPF32: new Float32Array(buffer),
        HEAPF64: new Float64Array(buffer)

    }
}

//##################################
//#           FOREIGN Fn           #
//##################################

function sort(ptr, length) {

}

const TurboASM = {
    Instance: function (bytes, shared) {
        var buffer = shared ? new SharedArrayBuffer(bytes) : new ArrayBuffer(bytes);

        if (buffer.byteLength < 16) {
            throw new Error("The memory is too small even for metadata");
        }

        return TurboASMWrapper(TurboModule(
            typeof stdlib !== 'undefined' ? stdlib : window,
            typeof foreign !== 'undefined' ? foreign : {
                    random: () => {
                        return Math.random() / Number.MAX_SAFE_INTEGER;
                    }
                },
            buffer
        ), buffer);
    }
};
